/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package main;

import comunicacao.AppDatabaseComunicator;
import comunicacao.GestorZooKeeper;
import comunicacao.GestorZooKeeper2;
import comunicacao.RmiAppInterface;
import entities.Lugar;
import entities.Resposta;
import entities.Teatro;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Leonardo Lino Nº45340
 * @author Diogo Pires Nº40351
 */
public class RecebeComunicacao extends java.rmi.server.UnicastRemoteObject
        implements RmiAppInterface {

    private int thisPort;
    private String thisAddress = "127.0.0.1";
    Registry registry; // rmi registry for lookup the remote objects.
    AppDatabaseComunicator appDB;
    Principal prin;
    GestorReservas reservas;
    ConfigGeral cg = new ConfigGeral();
    private GestorZooKeeper2 gzk;
    
    private boolean emFalha = false;
    

    public RecebeComunicacao(Principal principal) throws RemoteException {
        this.prin = principal;
        setPortIP();
        prin.dbInfoLabel.setText(ConfigGeral.CG_SERVER_DB_IP + ":" + ConfigGeral.CG_SERVER_DB_PORT);

    }

    public void startRecebe() throws RemoteException {
        reservas = new GestorReservas(prin, gzk);

        prin.appinfoLabel.setText(this.thisAddress + ":" + thisPort);

        try {
            // create the registry and bind the name and object.
            registry = LocateRegistry.createRegistry(thisPort);
            registry.rebind(ConfigGeral.CG_SERVER_APP_NAME, this);

        } catch (RemoteException e) {
            System.err.println(e);
        }

    }

    private void setPortIP() {

        BufferedReader br = null;

        try {
            br = new BufferedReader(new FileReader("config.txt"));
            StringBuilder sb = new StringBuilder();
            String line = br.readLine();

            while (line != null) {
                sb.append(line);
                line = br.readLine();
            }
            thisAddress = sb.toString();
            br.close();
        } catch (IOException ex) {
            Logger.getLogger(RecebeComunicacao.class.getName()).log(Level.SEVERE, null, ex);
        }

        thisPort = ConfigGeral.CG_SERVER_APP_PORT;

        while (!cg.availablePort(thisPort)) {
            thisPort++;
        }

    }

    @Override
    public Resposta listTheaters() throws RemoteException {
        
         if (emFalha)
            return null;
        
        Resposta resposta = null;
        //consola("LISTA TEATROS");

        ArrayList<String> lista = reservas.listTheaters();

        if (lista != null) {
            resposta = new Resposta();
            resposta.setEstado(Resposta.ESTADO_AVAILABLE);
            resposta.setTeatrosLista(lista);
        }
        return resposta;

    }

    @Override
    public Resposta getTheater(String theaterName) throws RemoteException {
        
         if (emFalha)
            return null;
        
        Resposta resposta = null;
        Lugar lugar = null;

        Teatro teatro = reservas.getTheater(theaterName);
        
        if (teatro==null){
            resposta = new Resposta();
            resposta.setEstado(Resposta.ESTADO_BUSY);
            return resposta;
        }
        
        
        ArrayList<Lugar> novaLista = new ArrayList<Lugar>();
        for (Lugar l : teatro.getLugares()) {
            
            if (l.getState() == Lugar.STATE_FREE){
                novaLista.add(lugar);
            } else {
                novaLista.add(l);
            }
        }
        teatro.setLugares(novaLista);
                
        

        if (teatro != null) {
            resposta = new Resposta();
            resposta.setEstado(Resposta.ESTADO_AVAILABLE);
            resposta.setTeatro(teatro);
        }

        return resposta;
    }

    @Override
    public Resposta reserveSeat(String theaterName, int lugarID, int userID) throws RemoteException {
        
         if (emFalha)
            return null;

        Resposta resposta = null;
        Teatro teatro = reservas.addReserva(theaterName, lugarID, userID);

        if (teatro != null) {
            resposta = new Resposta();
            resposta.setEstado(Resposta.ESTADO_AVAILABLE);
            resposta.setTeatro(teatro);
        }
        return resposta;
    }

    @Override
    public Resposta purchaseSeat(String theaterName, int lugarID, int userID) throws RemoteException {
        
        if (emFalha)
            return null;
        
        Resposta resposta = null;

        Teatro teatro = reservas.compraLugar(theaterName, lugarID, userID);

        resposta = new Resposta();
        if (teatro != null) {

            resposta.setEstado(Resposta.ESTADO_AVAILABLE);
            resposta.setTeatro(teatro);
        } else {
            resposta.setEstado(Resposta.ESTADO_BADCOMPRA);
            resposta.setTeatro(reservas.getTheater(theaterName));
        }
        return resposta;
    }

    public int getThisPort() {
        return thisPort;
    }

    public String getThisAddress() {
        return thisAddress;
    }

    @Override
    public boolean falha() throws RemoteException {
        consola("FALHA--------------");
        emFalha = true;
        return true;
    }

    @Override
    public boolean restart() throws RemoteException {
        consola("RESTART--------------");
        emFalha = false;
        return true;
    }

    public void setGzk(GestorZooKeeper2 gzk) {
        this.gzk = gzk;
    }

    private void consola(String msg) {

        if (Principal.showMsg) {
            prin.consola.append(msg + "\n");
        }
    }

}
